{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import cv2\n",
    "import numpy as np\n",
    "import torch\n",
    "import torchvision\n",
    "from torch import nn\n",
    "import torch.nn.functional as F\n",
    "from matplotlib import pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用opencv展示图片\n",
    "# def img_show_cv(img_name, img):\n",
    "#     cv2.imshow(img_name, img)\n",
    "#     cv2.waitKey(0)\n",
    "#     cv2.destroyAllWindows()\n",
    "\n",
    "# 使用matplotlib展示图片\n",
    "def img_show_plt(img):\n",
    "    plt.imshow(img, cmap=\"gray\")\n",
    "    plt.show()\n",
    "\n",
    "# 导入模型\n",
    "class CNN(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(CNN,self).__init__()\n",
    "        self.conv1 = nn.Conv2d(1,32,kernel_size=3,stride=1,padding=1)\n",
    "        self.pool = nn.MaxPool2d(2,2)\n",
    "        self.conv2 = nn.Conv2d(32,64,kernel_size=3,stride=1,padding=1)\n",
    "        # 两个池化，所以是7*7而不是14*14\n",
    "        self.fc1 = nn.Linear(64*7*7,1024)\n",
    "        self.fc2 = nn.Linear(1024,512)\n",
    "        self.fc3 = nn.Linear(512,10)\n",
    "\n",
    "    def forward(self,x):\n",
    "        x = self.pool(F.relu(self.conv1(x)))\n",
    "        x = self.pool(F.relu(self.conv2(x)))\n",
    "        # 将数据平整为一维的\n",
    "        x = x.view(-1, 64 * 7* 7)\n",
    "        x = F.relu(self.fc1(x))\n",
    "        x = F.relu(self.fc2(x))\n",
    "        x = self.fc3(x)\n",
    "        return x\n",
    "\n",
    "# 反相灰度图，将黑白阈值颠倒\n",
    "def accessPiexl(img):\n",
    "    height = img.shape[0]\n",
    "    width = img.shape[1]\n",
    "    for i in range(height):\n",
    "       for j in range(width):\n",
    "           img[i][j] = 255 - img[i][j]\n",
    "    return img\n",
    "\n",
    "# 反相二值化图像\n",
    "def accessBinary(image, threshold=128):\n",
    "    image_2 = accessPiexl(image)\n",
    "    # 边缘膨胀，不加也可以\n",
    "    kernel = np.ones((3, 3), np.uint8)\n",
    "    image_2 = cv2.dilate(image_2, kernel, iterations=1)\n",
    "    _, image_2 = cv2.threshold(image_2, threshold, 0, cv2.THRESH_TOZERO)\n",
    "    return image_2\n",
    "\n",
    "# 根据长向量找出顶点\n",
    "def extractPeek(array_vals, min_vals=10, min_rect=20):\n",
    "    extrackPoints = []\n",
    "    startPoint = None\n",
    "    endPoint = None\n",
    "    for i, point in enumerate(array_vals):\n",
    "        if point > min_vals and startPoint == None:\n",
    "            startPoint = i\n",
    "        elif point < min_vals and startPoint != None:\n",
    "            endPoint = i\n",
    "\n",
    "        if startPoint != None and endPoint != None:\n",
    "            extrackPoints.append((startPoint, endPoint))\n",
    "            startPoint = None\n",
    "            endPoint = None\n",
    "\n",
    "    # 剔除一些噪点\n",
    "    for point in extrackPoints:\n",
    "        if point[1] - point[0] < min_rect:\n",
    "            extrackPoints.remove(point)\n",
    "    return extrackPoints\n",
    "\n",
    "# 寻找边缘，返回边框的左上角和右下角（利用直方图寻找边缘算法（需行对齐））\n",
    "def findBorderHistogram(img):\n",
    "    borders = []\n",
    "    # 行扫描\n",
    "    hori_vals = np.sum(img, axis=1)\n",
    "    hori_points = extractPeek(hori_vals)\n",
    "    # 根据每一行来扫描列\n",
    "    for hori_point in hori_points:\n",
    "        extractImg = img[hori_point[0]:hori_point[1], :]\n",
    "        vec_vals = np.sum(extractImg, axis=0)\n",
    "        vec_points = extractPeek(vec_vals, min_rect=0)\n",
    "        for vect_point in vec_points:\n",
    "            border = [(vect_point[0], hori_point[0]), (vect_point[1], hori_point[1])]\n",
    "            borders.append(border)\n",
    "    return borders\n",
    "\n",
    "# 显示结果及边框\n",
    "def showResults(img, borders, results=None):\n",
    "    # 绘制\n",
    "    print(img.shape)\n",
    "    for i, border in enumerate(borders):\n",
    "        cv2.rectangle(img, border[0], border[1], (0, 0, 255))\n",
    "        if results:\n",
    "            cv2.putText(img, str(results[i]), border[0], cv2.FONT_HERSHEY_COMPLEX, 0.8, (0, 255, 0), 1)\n",
    "    # img_show_plt(img)\n",
    "\n",
    "# 根据边框转换为MNIST格式\n",
    "def transMNIST(img, borders, size=(28, 28)):\n",
    "    imgData = np.zeros((len(borders), size[0], size[0]), dtype='uint8')\n",
    "    img = accessBinary(img)\n",
    "    for i, border in enumerate(borders):\n",
    "        borderImg = img[border[0][1]:border[1][1], border[0][0]:border[1][0]]\n",
    "        # 根据最大边缘拓展像素\n",
    "        extendPiexl = (max(borderImg.shape) - min(borderImg.shape)) // 2\n",
    "        targetImg = cv2.copyMakeBorder(borderImg, 7, 7, extendPiexl + 7, extendPiexl + 7, cv2.BORDER_CONSTANT)\n",
    "        targetImg = cv2.resize(targetImg, size)\n",
    "        imgData[i] = targetImg\n",
    "    return imgData\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "[3, 1, 2, 5, 9, 8]"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def process(img_path):\n",
    "    img_raw = cv2.imread(img_path)\n",
    "    img_bin = cv2.cvtColor(img_raw, cv2.COLOR_BGR2GRAY)\n",
    "    _, img_bin = cv2.threshold(img_bin, 125, 255, cv2.THRESH_BINARY)\n",
    "    img_show_plt(img_bin)\n",
    "    accessBinary(img_bin)\n",
    "    model = CNN()\n",
    "    model.load_state_dict(torch.load(\"./mnist_net.pth\")) # 加载State模型\n",
    "    model.eval()\n",
    "    borders = findBorderHistogram(img_bin)\n",
    "    img_bin_back = accessBinary(img_bin)\n",
    "    imgData = transMNIST(img_bin_back, borders)\n",
    "    label_lst = []\n",
    "    with torch.no_grad():\n",
    "        for i, img in enumerate(imgData):\n",
    "            name = './cut_dir/test_' + str(i) + '.jpg'\n",
    "            cv2.imwrite(name, img)\n",
    "            # print(img.shape)\n",
    "            img = np.array(img).astype(np.float32)\n",
    "            img = np.expand_dims(img, axis=0)\n",
    "            img_tensor = torch.from_numpy(img)\n",
    "            i = img_tensor\n",
    "            _, preds = torch.max(model(i), dim=1)\n",
    "            label_lst.append(preds.cpu().numpy()[0])\n",
    "    return label_lst\n",
    "process(\"./raw_pic/nums_set.jpg\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
